package com.huilian.iotbox.mqtt.server.base.handler.penetrate.vendmach;

import com.huilian.iotbox.aliyun.service.PubService;
import com.huilian.iotbox.data.cmd.PositiveDataFrameCMD;
import com.huilian.iotbox.data.cmd.VendmachPositiveDataFrameCMD;
import com.huilian.iotbox.data.cmd.VendmachResponseDataFrameCMD;
import com.huilian.iotbox.data.common.RedisKey;
import com.huilian.iotbox.data.dto.DisplayRackItemDto;
import com.huilian.iotbox.data.dto.OrderDto;
import com.huilian.iotbox.data.utils.IotBoxUtil;
import com.huilian.iotbox.data.vo.DeviceVo;
import com.huilian.iotbox.data.vo.DisplayRackItemVo;
import com.huilian.iotbox.data.vo.OrderItemVo;
import com.huilian.iotbox.mqtt.server.base.handler.penetrate.PenetrateHandlerStrategy;
import com.huilian.iotbox.mqtt.server.base.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author 谢洛涛
 * @date 2024/1/6 18:02
 */
@Slf4j
@Service("penetrateHandlerServiceC90F")
public class LatticeShipmentC90FHandler  implements PenetrateHandlerStrategy {

    @Value("${huilian.iot.productKey}")
    private String productKey;
    @Autowired
    private PubService pubService;
    @Autowired
    DeviceService deviceService;
    @Autowired
    private OrderService orderService;
    @Resource
    private OrderItemService orderItemService;
    @Resource
    private RabbitSenderService rabbitSenderService;
    @Resource
    private DisplayRackItemService displayRackItemService;
    @Autowired
    private RedisTemplate<String, Serializable> redisCacheTemplate;
    @Override
    public void process(String content, String deviceNo, Integer positionId) throws Exception {
        log.info("进入格子机售货机是否收到订阅消息:{}",content);

        DeviceVo deviceVo = deviceService.findOneDeviceByDeviceNo(deviceNo);
        // 支付唯一码
        final String payNoHex = content.substring(10, 22);
        log.info("payNoHex：" + payNoHex);
        final String payNo = IotBoxUtil.convertHexToString(payNoHex).trim();
        log.info("payNo：" + payNo);
        final String controlBoardCmd = content.substring(26, 28);
        log.info("controlBoardCmd：" + controlBoardCmd);
        //  目前格子机没有看到有电机测试的协议，所以这边加了个查询，如果能查询到就是支付出货的，如果不能查询到就是电机测试
        OrderDto condition = new OrderDto();
        condition.setDeviceNo(deviceNo);
        condition.setPayNo(payNo);
        final String deviceAddress = content.substring(22, 26);
        if(controlBoardCmd.equals("03") || controlBoardCmd.equals("FF")){
            log.info("进入出货状态:{}",content);
            Integer doorNumber = IotBoxUtil.singleHex2Int(content.substring(28, 30)); // 门编号
            final Integer state = IotBoxUtil.singleHex2Int(content.substring(30, 32));
            final Integer line = ((doorNumber - 1) / 10) + 1;
            final Integer rank = doorNumber % 10;
            OrderItemVo orderItem = orderItemService.findOrderItem(payNo,deviceVo.getDeviceNo());
            if (StringUtils.isEmpty(orderItem)) {
                log.info(deviceNo + "格子机获取点击测试消息: {}", content);

                //获取到检测结果直接修改
                DisplayRackItemDto updateDisplayRackItemDto = new DisplayRackItemDto();
                updateDisplayRackItemDto.setDeviceId(deviceVo.getId());
                updateDisplayRackItemDto.setHierarchy(line);
                updateDisplayRackItemDto.setFreightLane(rank);
                updateDisplayRackItemDto.setStatus(!state.equals(1));
                displayRackItemService.updateStatus(updateDisplayRackItemDto);

                String detectionKey = String.format(RedisKey.MOTOR_TEST_REFRESH_TIME, deviceVo.getId());
                Integer testingNumber = (Integer) redisCacheTemplate.opsForValue().get(detectionKey);
                if (!StringUtils.isEmpty(testingNumber)){
                    testingNumber--;
                    if (testingNumber != 0){
                        redisCacheTemplate.opsForValue().set(detectionKey, testingNumber, testingNumber * 5L, TimeUnit.SECONDS);
                    }else{
                        redisCacheTemplate.delete(detectionKey);
                    }
                }
                //查询故障数
                DisplayRackItemDto selectDisplayRackItemDto = new DisplayRackItemDto();
                selectDisplayRackItemDto.setDeviceId(deviceVo.getId());
                selectDisplayRackItemDto.setStatus(true);
                selectDisplayRackItemDto.setHierarchy(line);
                int numberOfFailures = displayRackItemService.numberOfFailures(selectDisplayRackItemDto);
                // 格子机返回的是1是成功，其他都是失败
                if (state.equals(1)){
                    deviceVo.setMotorStatus(1);
                }else{
                    deviceVo.setMotorStatus(2);
                }
                deviceVo.setHierarchy(line);
                deviceVo.setFreightLane(rank);
                deviceVo.setNumberOfFailures(numberOfFailures);
                //发webSock的MQ
                rabbitSenderService.disposeMotorTestingResult(deviceVo);

                String penetrateTcp = PositiveDataFrameCMD.penetrate(VendmachResponseDataFrameCMD.LatticeShipmentReport(deviceAddress, payNo, "03",doorNumber,state));
                pubService.pub(penetrateTcp, deviceNo, productKey);
                String random = RandomStringUtils.random(6, true, true);
                String wapKey = String.format(RedisKey.VENDING_MACHINE_TEST_WAP, deviceVo.getDeviceNo());
                List<DisplayRackItemVo> displayRackItemVoList = (List<DisplayRackItemVo>) redisCacheTemplate.opsForValue().get(wapKey);
                if(!StringUtils.isEmpty(displayRackItemVoList) && displayRackItemVoList.size()>0){
                    log.info("商家端缓存参数: {}", displayRackItemVoList.size());
                    String command = PositiveDataFrameCMD.penetrate(VendmachPositiveDataFrameCMD.LatticeShipment(random, displayRackItemVoList.get(0).getHierarchy(),displayRackItemVoList.get(0).getFreightLane()));
                    pubService.pub(command, deviceVo.getDeviceNo(), productKey);
                    displayRackItemVoList.remove(0);
                    redisCacheTemplate.opsForValue().set(wapKey, (Serializable) displayRackItemVoList, 10, TimeUnit.MINUTES);
                }
                String clientKey = String.format(RedisKey.VENDING_MACHINE_TEST_CLIENT, deviceVo.getDeviceNo());
                List<DeviceVo> DeviceVoList = (List<DeviceVo>) redisCacheTemplate.opsForValue().get(clientKey);

                if(!StringUtils.isEmpty(DeviceVoList) && DeviceVoList.size()>0){
                    log.info("用户端缓存参数: {}", DeviceVoList.size());
                    String command = PositiveDataFrameCMD.penetrate(VendmachPositiveDataFrameCMD.LatticeShipment(random, DeviceVoList.get(0).getHierarchy(),DeviceVoList.get(0).getFreightLane()));
                    pubService.pub(command, deviceVo.getDeviceNo(), productKey);
                    DeviceVoList.remove(0);
                    redisCacheTemplate.opsForValue().set(clientKey, (Serializable) DeviceVoList, 10, TimeUnit.MINUTES);
                }

            } else {
                if(controlBoardCmd.equals("FF")){
                    log.info("格子机重复出货成功回复: {}", content);
                }
                log.info(deviceNo + "获取售货机出货消息: {}", content);
                // 处理出货
                String key = String.format(RedisKey.VENDING_MACHINE_PROCESSING_STATUS, deviceNo, payNo);
                Integer interceptState = (Integer) redisCacheTemplate.opsForValue().get(key);
                if (interceptState == null) {
                    // 正常2秒内能处理好，但防止真的有20个商品的订单，所以加成10秒
                    redisCacheTemplate.opsForValue().set(key, 1, 10, TimeUnit.SECONDS);
                    Boolean bool = orderService.LatticeProcessingShipments(deviceVo, payNo, productKey, line, rank, state);
                    if (bool) {
                        String penetrateTcp = PositiveDataFrameCMD.penetrate(VendmachResponseDataFrameCMD.LatticeShipmentReport(deviceAddress, payNo, "03",doorNumber,state));
                        pubService.pub(penetrateTcp, deviceNo, productKey);
                        redisCacheTemplate.delete(key);
                    }
                } else {
                    log.info("当前订单状态正在处理中:{}", payNo);
                }
            }
        }
    }
}
